// panda.h
//
//	TSeqHash
//	TAccHash

//		Structures storing hashes of Sequences and Accession lines

#if !defined(PANDA_H)
#define PANDA_H


#include <string>
#include <iosfwd>
#include <vector>
#include <deque>
#include "md4.h"
//#include "components/crc.h"
#include <boost/static_assert.hpp>

inline t_digest& digest_message(	const std::string::const_iterator p,
							const std::string::const_iterator& end,
							t_digest& hash)
{
	return md4_hash(p, end, hash);
}

inline t_digest& digest_message(const std::string& s, t_digest& hash)
{
	return md4_hash(s.begin(), s.end(), hash);
}
struct op_cmp_digest
{
	bool operator()(const t_digest& a, const t_digest& b)
	{
		return a < b;
	}
};

typedef unsigned t_pi;
typedef unsigned t_id;

struct t_id_pos
{
	t_id		id;
	unsigned	pos;
	unsigned	len;
					t_id_pos(t_id id_, unsigned pos_, unsigned len_):
									id(id_), pos(pos_), len(len_){}
};

struct op_invalid_len
{
	bool operator() (const t_id_pos& a) const
	{ return a.len == 0; }
};


//________________________________________________________________________________________
//	t_hash_len
//________________________________________________________________________________________
struct t_hash_pos : public t_digest
{
	unsigned	pos;
	unsigned	len;
				t_hash_pos(const t_digest& hash_, unsigned pos_, unsigned len_)
					:t_digest(hash_), pos(pos_), len(len_){}
};
//used inherited comparisons
inline bool	operator == (const t_hash_pos& a, const t_hash_pos& b)
{   return	static_cast<const t_digest&>(a) == static_cast<const t_digest&>(b);		}
inline bool operator < (const t_hash_pos& a, const t_hash_pos& b)
{   return	static_cast<const t_digest&>(a) < static_cast<const t_digest&>(b);		}


template<typename T_> struct op_cmp_filepos
{
	bool operator()(const T_& a, const T_& b) const
	{
		return a.pos < b.pos;
	}
};

template<typename T_> struct op_cmp_id
{
	bool operator()(const T_& a, const T_& b) const
	{
		return a.id < b.id;
	}
};

template<typename T_> struct op_eq_id
{
	bool operator()(const T_& a, const T_& b) const
	{
		return a.id == b.id;
	}
};


//________________________________________________________________________________________
//	t_hash_id
//________________________________________________________________________________________
struct t_hash_id : public t_digest
{
	t_id		id;
				t_hash_id(const t_digest& crc_, t_id id_)
					:t_digest(crc_), id(id_){}
				t_hash_id(){}
				t_hash_id(const t_digest& crc_)
					:t_digest(crc_){}
};

//used inherited comparisons
inline bool operator == (const t_hash_id& a, const t_hash_id& b)
{   return	static_cast<const t_digest&>(a) == static_cast<const t_digest&>(b);		}
inline bool operator < (const t_hash_id& a, const t_hash_id& b)
{   return	static_cast<const t_digest&>(a) < static_cast<const t_digest&>(b);		}


struct op_empty_accid
{
	bool operator() (const t_hash_id& a) const
	{ return a.id == (t_id)-1; }
};

struct op_get_id
{
	t_id operator() (const t_hash_id& a) const
	{ return a.id; }
};

//________________________________________________________________________________________
//	t_hash_id
//________________________________________________________________________________________
struct t_hash_id_pos : public t_hash_id
{
	unsigned	pos;
	unsigned	len;
				t_hash_id_pos(const t_digest& hash_, t_id id_, unsigned pos_, unsigned len_)
					:t_hash_id(hash_, id_), pos(pos_), len(len_){}
};

//used inherited comparisons
inline bool operator == (const t_hash_id_pos& a, const t_hash_id_pos& b)
{   return	static_cast<const t_digest&>(a) == static_cast<const t_digest&>(b);		}
inline bool operator < (const t_hash_id_pos& a, const t_hash_id_pos& b)
{   return	static_cast<const t_digest&>(a) < static_cast<const t_digest&>(b);		}


struct op_zero_len
{
	bool operator()(const t_hash_id_pos& a) const
	{
		return a.len == 0;
	}
};


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//		Auxillary functions for saving records

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
template<typename T> struct op_save_in_vector
{
	op_save_in_vector(std::vector<T>& vec_)
		:		vec(vec_){}
	std::vector<T>&			vec;
	void operator ()(const T& t)
	{		vec.push_back(t);	}
};
template<typename T> struct op_save_in_deque
{
	op_save_in_deque(std::deque<T>& dec_)
		:		dec(dec_){}
	std::deque<T>&			dec;
	void operator ()(const T& t)
	{		dec.push_back(t);	}
};



#endif	// PANDA_H


